<?php
/**
 * This file is part of Hyperf Mall.
 *
 * @link     https://gitee.com/scwlkj/hyperf_mall
 * @contact  hyperf_mall@163.com
 */

namespace App\Repository;

use App\Common\OidBuild;
use App\Constants\Message;
use App\Constants\OrderConstant;
use App\Exception\BaseException;
use App\Model\OrderModel;
use App\Service\Activity\CouponReceiveService;
use App\Service\Config\AreaService;
use App\Service\Goods\GoodsService;
use App\Service\Goods\ProductService;
use App\Service\Member\AddressService;
use App\Service\Member\MemberService;
use App\Service\Member\MessageService;
use App\Utils\DB;
use App\Utils\Log;
use Hyperf\Di\Annotation\Inject;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Swoole\Exception;

class OrderRepository extends BaseRepository
{
    /**
     * @Inject
     * @var OrderModel
     */
    protected $model;

    /**
     * @Inject()
     * @var AreaService
     */
    protected AreaService $areaService;

    /**
     * @Inject
     * @var MessageService
     */
    protected MessageService $messageService;

    /**
     * @Inject
     * @var GoodsService
     */
    protected GoodsService $goodsService;

    /**
     * @Inject
     * @var ProductService
     */
    protected ProductService $productService;

    /**
     * @Inject
     * @var OrderDetailRepository
     */
    protected OrderDetailRepository $orderDetailRepository;

    /**
     * @Inject
     * @var OrderAddressRepository
     */
    protected OrderAddressRepository $orderAddressRepository;

    /**
     * @Inject
     * @var PreOrderRepository
     */
    protected PreOrderRepository $preOrderRepository;

    /**
     * @Inject
     * @var CartRepository
     */
    protected CartRepository $cartRepository;

    /**
     * @Inject
     * @var OrderPayRepository
     */
    protected OrderPayRepository $orderPayRepository;

    /**
     * @Inject
     * @var OrderPayOrderRepository
     */
    protected OrderPayOrderRepository $orderPayOrderRepository;

    /**
     * @Inject
     * @var MemberService
     */
    protected MemberService $memberService;

    /**
     * @Inject
     * @var CouponReceiveService
     */
    protected CouponReceiveService $couponReceiveService;

    /**
     * @Inject
     * @var OrderDiscountRepository
     */
    protected OrderDiscountRepository $orderDiscountRepository;

    /**
     * Notes: 购物车提交订单
     * Author: Bruce.z
     * DateTime: 2022/7/22 9:59
     * @param $data
     * @return array
     * @throws BaseException
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function baseAdd($data): array
    {
        $cart_goods = $this->preOrderRepository->cartGoods($data['cartId']??[], $data['member_id']);
        $amount = $goods_price = $this->preOrderRepository->subMoney($cart_goods);
        $goods_number = array_sum(array_column($cart_goods, 'number'));

        $discount_price = 0;$res=[];
        if(!empty($data['coupon_receive_id'])){
            $res = $this->handleCoupon($goods_price, $data['coupon_receive_id'],$cart_goods);
            $amount = bcsub((string)$amount, (string)$res['discount_price'], 2);
            $discount_price = $res['discount_price'];
        }

        $this->checkStock($cart_goods);

        $oid = OidBuild::getInstance()->getOid();
        $pay_id= OidBuild::getInstance()->getPayId($data['member_id']);
        DB::beginTransaction();
        try{
            $this->makeOrder($oid, $data['member_id'], $goods_price , $goods_number, $data['desc'],$pay_id, $discount_price);
            $this->makeOrderDetail($oid, $data['member_id'], $cart_goods, $goods_price,$discount_price);
            $this->makeOrderAddress($oid, $data['address_id']);
            $this->makeOrderPay($data['member_id'], $amount, $pay_id);
            $this->makePayOrder($data['member_id'], $oid, $pay_id);
            $this->cartRepository->removeByIds($data['cartId']??[],$data['member_id']);

            if(!empty($data['coupon_receive_id'])){
                $this->makeDiscount($oid, $data['coupon_receive_id'], $res);
            }

            DB::commit();
        }catch (Exception $e){
            DB::rollBack();
            if(!empty($data['coupon_receive_id'])){
                // 回滚优惠券未使用状态
                $this->couponReceiveService->update($data['coupon_receive_id'], ['status'=>0]);
            }
            Log::getInstance()->error(__METHOD__, [$e->getMessage(),$e->getCode()]);
            throw new BaseException(BaseException::BASE_ERROR, $e->getMessage());
        }

        try {
            // 站内信消息
            $this->messageService->orders($oid, $data['member_id'], Message::MS_CREATE_ORDER);
        }catch (Exception $e){
            Log::getInstance()->error('站内信添加失败',[$e->getMessage()]);
        }
        return ['oid'=>$oid, 'amount'=>$amount];
    }

    /**
     * Notes: 单商品直接购买
     * Author: Bruce.z
     * DateTime: 2022/7/22 9:58
     * @param array $data
     * @return array
     * @throws BaseException
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function buy(array $data):array
    {
        $goods = $this->preOrderRepository->getBuyGoods($data['goods_id'], $data['product_id']);
        $amount = $goods_price = round($goods['retail_price']*$data['number'], 2);

        $discount_price = 0;$res=[];
        if(!empty($data['coupon_receive_id'])){
            $res = $this->handleCoupon($goods_price, $data['coupon_receive_id']);
            $amount = bcsub((string)$amount, (string)$res['discount_price'], 2);
            $discount_price = $res['discount_price'];
        }
        $this->checkStockOne($goods, $data['number']);

        $oid = OidBuild::getInstance()->getOid();
        $pay_id= OidBuild::getInstance()->getPayId($data['member_id']);

        DB::beginTransaction();
        try {
            $this->makeOrder($oid, $data['member_id'], $goods_price , $data['number'], $data['desc'],$pay_id, $discount_price);
            $this->makeOrderDetailOne($oid, $data['member_id'], $goods, $data['number'],$discount_price);
            $this->makeOrderAddress($oid, $data['address_id']);
            $this->makeOrderPay($data['member_id'], $amount, $pay_id);
            $this->makePayOrder($data['member_id'], $oid, $pay_id);

            if(!empty($data['coupon_receive_id'])){
                $this->makeDiscount($oid, $data['coupon_receive_id'], $res);
            }

            DB::commit();
        }catch (Exception $e){
            DB::rollBack();
            if(!empty($data['coupon_receive_id'])){
                // 回滚优惠券未使用状态
                $this->couponReceiveService->update($data['coupon_receive_id'], ['status'=>0]);
            }
            Log::getInstance()->error(__METHOD__, [$e->getMessage(),$e->getCode()]);
            throw new BaseException(BaseException::BASE_ERROR, $e->getMessage());
        }

        try {
            // 站内信消息
            $this->messageService->orders($oid, $data['member_id'], Message::MS_CREATE_ORDER);
        }catch (Exception $e){
            Log::getInstance()->error('站内信添加失败',[$e->getMessage()]);
        }

        return ['oid'=>$oid, 'amount'=>$amount];
    }

    private function makeOrder($oid, $member_id, $goods_price, $goods_num, $desc, $pay_id, $discount_price = 0):void
    {
        $_data = [
            'oid'               =>$oid,
            'member_id'         =>$member_id,
            'goods_num'         =>$goods_num,
            'goods_price'       =>$goods_price,
            'total_cost_price'  =>0,
            'total_price'       =>$goods_price,
            'distribution_price'=>0,
            'discount_price'    =>$discount_price,
            'price'             =>bcsub((string)$goods_price, (string)$discount_price, 2),
            'message'           =>$desc,
            'order_pay_id'      =>$pay_id,
        ];

        $this->model->baseAdd($_data);
    }

    private function makeOrderDetail($oid, $member_id, $cart_goods,$goods_price,$discount_price = 0):void
    {
        $detail = [];
        array_map(function ($cart) use (&$detail, $oid, $member_id,$goods_price,$discount_price){
            $_discount_price = 0;
            $_goods_price = round($cart['goods']['retail_price']*$cart['number'], 2);
            if($discount_price > 0){
                $_discount_price = round($discount_price*$_goods_price/$goods_price, 2);
            }
            $detail[] = [
                'oid'           =>$oid,
                'saas_id'       =>get_saas_id(),
                'goods_id'      =>$cart['goods_id'],
                'product_id'    =>$cart['product_id'],
                'member_id'     =>$member_id,
                'goods_name'    =>$cart['goods']['name'],
                'spec'          =>$cart['goods']['spec_name']??'',
                'num'           =>$cart['number'],
                'product_image' =>$cart['goods']['img'],
                'retail_price'  =>$cart['goods']['retail_price'],
                'cost_price'    =>$cart['goods']['cost_price'],
                'total_price'   =>$_goods_price,
                'discount_price'=>$_discount_price,
                'price'         =>bcsub((string)$_goods_price, (string)$_discount_price, 2),
                'weight'        =>0,
            ];
        }, $cart_goods);

        $this->orderDetailRepository->batchAdd($detail);
    }

    /**
     * Notes: 单个商品购买 - 生成订单详情
     * Author: Bruce.z
     * DateTime: 2022/7/22 9:58
     * @param $oid
     * @param $member_id
     * @param $goods
     * @param $number
     */
    private function makeOrderDetailOne($oid, $member_id, $goods, $number, $discount_price = 0):void
    {
        $goods_price = round($goods['retail_price']*$number,2);
        $detail = [
            'oid'           =>$oid,
            'saas_id'       =>get_saas_id(),
            'goods_id'      =>$goods['id'],
            'product_id'    =>$goods['product_id'] ?? 0,
            'member_id'     =>$member_id,
            'goods_name'    =>$goods['name'],
            'spec'          =>$goods['spec_name']??'',
            'num'           =>$number,
            'product_image' =>$goods['img'],
            'retail_price'  =>$goods['retail_price'],
            'cost_price'    =>$goods['cost_price'],
            'total_price'   =>round($goods['retail_price']*$number,2),
            'discount_price'=>$discount_price,
            'price'         =>round($goods_price-$discount_price,2),
            'weight'        =>0,
        ];

        $this->orderDetailRepository->baseAdd($detail);
    }

    private function makeOrderAddress($oid, $address_id):void
    {
        $address = AddressService::getInstance()->getOne(['id'=>$address_id], ['*']);
        $_data = [
            'oid'           =>$oid,
            'member_id'     =>$address['member_id'],
            'ship_mobile'   =>$address['ship_mobile'],
            'ship_name'     =>$address['ship_name'],
            'ship_area'     =>$this->areaService->address($address['ship_county_id']),
            'ship_addr'     =>$address['ship_addr'],
            'address_id'    =>$address_id,
            'lng'           =>$address['lng'],
            'lat'           =>$address['lat'],
        ];

        $this->orderAddressRepository->baseAdd($_data);
    }


    public function makeOrderPay($member_id, $price, $pay_id):void
    {
        $this->orderPayRepository->baseAdd([
            'id' => $pay_id,
            'member_id' => $member_id,
            'pay_price' => $price,
            'pay_update_price' => $price,
            'status' => OrderConstant::ORDER_PAY_STATUS_WAIT,     // 待支付状态
        ]);
    }

    // 处理优惠券 订单优惠详情
    public function makeDiscount($oid, $coupon_receive_id, array $coupon_data)
    {
        $coupon = $coupon_data['coupon'];
        $this->orderDiscountRepository->baseAdd([
            'oid'=>$oid,
            'name'=>$coupon['name']??'',
            'param_id'=>$coupon_receive_id,
            'discount_price'=>$coupon_data['discount_price'],
            'free_type'=>$coupon['free_type'],
            'primary_id'=>$coupon['coupon_id'],
        ]);

        // 更新优惠券已使用
        $this->couponReceiveService->update($coupon_receive_id,['status'=>1]);
    }

    public function makePayOrder($member_id, $oid, $pay_id):void
    {
        $this->orderPayOrderRepository->baseAdd([
            'order_pay_id' => $pay_id,
            'member_id' => $member_id,
            'oid' => $oid,
        ]);
    }

    /**
     * Notes: c端会员订单列表
     * Author: Bruce.z
     * DateTime: 2022/7/14 9:09
     * @param array $condition
     * @param int $page
     * @param int $size
     * @return array
     */
    public function appIndex(array $condition, int $page, int $size):array
    {
        $orders = $this->getPageRows($condition, ['oid','status','create_time','price','goods_num','after_status'], $page, $size);
        if(!$orders['total']) return ['total'=>0, 'data'=>[]];

        $oids = array_column($orders['data'], 'oid');

        $details = $this->orderDetailRepository->getRows(['oid'=>$oids],['id','goods_id','product_id','goods_name','spec','retail_price','price','after_status','product_image','oid','num']);
        $details = collect($details);

        array_walk($orders['data'], function (&$re) use ($details){
            $re['goods'] = array_values($details->where('oid', $re['oid'])->toArray());
            $re['create_time'] = date('Y/m/d H:i:s', $re['create_time']);
        });
        $orders['data'] = array_values($orders['data']);

        return $orders;
    }

    public function info($oid) :array
    {
        $order_pay_order = $this->orderPayOrderRepository->getOne(['oid'=>$oid],['order_pay_id']);
        $pay = $this->orderPayRepository->getOne(['id'=>$order_pay_order['order_pay_id']], ['pay_price']);
        return [
            'amount' => $pay['pay_price'],
            'oid' => $oid,
            'pay_id' => $order_pay_order['order_pay_id'],
        ];
    }

    /**
     * Notes: 取消订单
     * Author: Bruce.z
     * DateTime: 2022/7/15 14:25
     * @param $oid
     * @return bool
     */
    public function cancel($oid):bool
    {
        if($this->updateByConditions(['oid'=>$oid,'status'=>OrderConstant::ORDER_STATUS_WAIT_PAY],
        ['status'=>OrderConstant::ORDER_STATUS_CANCEL,'cancel_time'=>time()])){
            $re = $this->getOne(['oid'=>$oid], ['order_pay_id','oid']);
            return $this->orderPayRepository->updateByConditions(['id'=>$re['order_pay_id']] , ['status'=>OrderConstant::ORDER_PUSH_STATUS_CANCEL]);
        }
        return false;
    }

    /**
     * Notes: c端 获取订单详情
     * Author: Bruce.z
     * DateTime: 2022/7/15 15:31
     * @param $oid
     * @return array
     */
    public function appDetail($oid) : array
    {
        $order = $this->getOne(['oid'=>$oid], ['oid','price','goods_num','message','total_price','goods_price','distribution_price','member_id','status','order_pay_id','after_status','create_time','order_pay_time','delivery_time','update_time','cancel_time','confirm_time','payment_type','discount_price','price','goods_num']);

        $order['goods'] = $this->orderDetailRepository->getRows(['oid'=>$oid], ['id','goods_name','num','spec','retail_price','total_price','price','product_image','delivery_status','after_status','discount_price','goods_id']);

        $order['address'] = $this->orderAddressRepository->getOne(['oid'=>$oid],['ship_area','ship_addr','ship_name','ship_mobile']);

        $order['member'] = $this->memberService->getOne(['id'=>$order['member_id']], ['id','username','tel']);
        $order['status_text'] = OrderConstant::$orderStatusName[$order['status']];
        $order['create_time'] = date('Y/m/d H:i:s', $order['create_time']);
        $order['update_time'] = date('Y/m/d H:i:s', $order['update_time']);
        $order['cancel_time'] = $order['cancel_time'] ? date('Y/m/d H:i:s', $order['cancel_time']) : '';
        $order['confirm_time'] = $order['confirm_time'] ? date('Y/m/d H:i:s', $order['confirm_time']) : '';
        $order['order_pay_time'] = $order['order_pay_time'] ? date('Y/m/d H:i:s', $order['order_pay_time']):'';
        $order['delivery_time'] = $order['delivery_time'] ? date('Y/m/d H:i:s', $order['delivery_time']):'';

        return $order;
    }

    /**
     * Notes: 会员中心首页统计数据
     * Author: Bruce.z
     * DateTime: 2022/7/19 14:46
     * @param int $member_id
     * @return array
     */
    public function appMemberIndex(int $member_id):array
    {
        $res = $this->_searchFactor(['member_id'=>$member_id,['status','<>',OrderConstant::ORDER_STATUS_CANCEL]])
            ->select(['status',DB::raw('count(oid) as count')])
            ->groupBy('status')->get()->toArray();
        return array_column($res,'count','status');
    }

    /**
     * Notes: A 端 订单列表
     * Author: Bruce.z
     * DateTime: 2022/8/9 9:58
     * @param array $condition
     * @param int $page
     * @param int $size
     * @return array
     */
    public function list(array $condition, int $page, int $size): array
    {
        $field = ['oid','member_id','total_price','price','distribution_price','status','activity_type','create_time','payment_type','discount_price'];

        if(isset($condition['oid'])){
            $condition[] = ['oid','like','%'.$condition['oid'].'%'];
            unset($condition['oid']);
        }

        $list = $this->getPageRows($condition, $field, $page, $size);

        if($list['total']){
            $oids = array_column($list['data'], 'oid');
            $goods = $this->orderDetailRepository->getRows(['oid'=>$oids], ['oid','goods_name','num','spec','retail_price','total_price','price','product_image']);

            $order_address = $this->orderAddressRepository->getRows(['oid'=>$oids],['oid','ship_name','ship_mobile']);
            $order_address = array_column($order_address,null, 'oid');

            $member_ids = array_unique(array_column($list['data'],'member_id'));
            $members = $this->memberService->getRows(['id'=>$member_ids], ['id','username']);
            $members = array_column($members,null, 'id');

            $_tmp = [];
            foreach ($goods as $row){
                $_tmp[$row['oid']][] = $row;
            }

            foreach ($list['data'] as &$res){
                $res['goods'] = $_tmp[$res['oid']];
                $res['status_text'] = OrderConstant::$orderStatusName[$res['status']];;
                $res['ship_name'] = $order_address[$res['oid']]['ship_name'] ?? '';
                $res['ship_mobile'] = $order_address[$res['oid']]['ship_mobile'] ?? '';
                $res['username'] = $members[$res['member_id']]['username'] ?? '';
            }

            ksort($list['data']);
        }

        return $list;
    }


    /**
     * Notes: A端订单详情
     * Author: Bruce.z
     * DateTime: 2022/8/10 15:31
     * @param $oid
     * @return array
     */
    public function orderDetail($oid): array
    {
        return $this->appDetail($oid);
    }

    /**
     * Note:发货
     * Author:Jurij.cao
     * Date:2022/8/11
     * @param $param
     * @return bool
     * @return bool
     * @throws BaseException
     */
    public function delivery($param): bool
    {

        $oid = $param['oid'] ?? '';
        $logiNo = $param['logi_no'] ?? '';
        $logiCode = $param['logi_code'] ?? '';
        $detailIds = $param['detail_ids'] ?? [];
        if (empty($oid) || empty($logiNo) || empty($logiCode)) {
            return false;
        }
        $conditions = ['oid' => $oid];
        $order = $this->getOne($conditions,['oid','member_id','status']);
        if ($order['status'] != OrderConstant::ORDER_STATUS_PAYED){
            throw new BaseException(BaseException::BASE_ERROR,'未满足发货状态');
        }

        $orderDetail = $this->orderDetailRepository->getRows($conditions);
        if (!empty($detailIds)) {
            $conditions ['id'] = $detailIds;
        }
        $noDeliveryOrderDetail = array_filter($orderDetail, function ($value) {
            return empty($value['logi_no']) && empty($value['logi_code']);
        });

        DB::beginTransaction();
        try {
            $updateCount = $this->orderDetailRepository->updateByConditions($conditions, [
                'logi_no' => $logiNo,
                'logi_code' => $logiCode,
                'delivery_status' => OrderConstant::ORDER_DETAIL_STATUS_SEND
            ]);
            if (count($noDeliveryOrderDetail) == $updateCount) {
                $updateCount = $this->updateByConditions(['oid' => $oid], [
                    'status' => OrderConstant::ORDER_STATUS_SEND ,
                    'delivery_time' => time() ,
                ]);
                $this->messageService->orders($oid, $order['member_id'], Message::MS_ORDER_DELIVERY);
            }
            DB::commit();
        } catch (Exception $e) {
            DB::rollBack();
            Log::getInstance()->debug('发货失败', ['exception' => $e]);
        }
        return !empty($updateCount);
    }

    /**
     * Notes: 检查库存 兼容无规格和多规格混搭 下单前/支付前
     * Author: Bruce.z
     * DateTime: 2022/8/11 15:57
     * @param $order_detail
     * @throws BaseException
     */
    public function checkStock($order_detail):void
    {
        $product_ids = $goods_ids = [];
        foreach ($order_detail as $g){
            if($g['product_id']) $product_ids[] = $g['product_id'];
            else $goods_ids[] = $g['goods_id'];
        }
        // 检查库存
        if(count($product_ids)){
            $order_detail = array_column($order_detail,null, 'product_id');
            $stocks = $this->productService->getRows(['id'=>$product_ids], ['id', 'stock']);
            foreach ($stocks as $val){
                if($val['stock'] < $order_detail[$val['id']]['num']){
                    throw new BaseException(BaseException::BASE_ERROR, '商品库存不足，无法完成支付下单');
                }
            }
        }

        if(count($goods_ids)){
            $order_detail = array_column($order_detail,null, 'goods_id');
            $stocks = $this->goodsService->getRows(['id'=>$goods_ids], ['id', 'stock']);
            foreach ($stocks as $val){
                if($val['stock'] < $order_detail[$val['id']]['num']){
                    throw new BaseException(BaseException::BASE_ERROR, '商品库存不足，无法完成支付下单');
                }
            }
        }
    }

    /**
     * Notes: 检测单个商品购买时库存
     * Author: Bruce.z
     * DateTime: 2022/8/11 16:06
     * @param array $goods
     * @param int $number
     * @throws BaseException
     */
    public function checkStockOne(array $goods, int $number):void
    {
        if($goods['product_id']){
            $stock = $this->productService->getOne(['id'=>$goods['product_id']], ['id', 'stock']);
        }else{
            $stock = $this->goodsService->getOne(['id'=>$goods['goods_id']], ['id', 'stock']);
        }

        if($stock < $number){
            throw new BaseException(BaseException::BASE_ERROR, '商品库存不足，无法完成支付下单');
        }
    }

    /**
     * Notes: 管理员支付
     * Author: Bruce.z
     * DateTime: 2022/8/11 16:08
     * @param $oid
     * @throws BaseException
     */
    public function payed($oid): bool
    {
        $re = $this->getOne(['oid'=>$oid], ['order_pay_id','oid','member_id']);
        $goods = $this->orderDetailRepository->getRows(['oid'=>$oid], ['goods_id','num','product_id']);

        $this->checkStock($goods);

        DB::beginTransaction();
        try {
            $this->updateByConditions(['oid'=>$oid,'status'=>OrderConstant::ORDER_STATUS_WAIT_PAY],
                ['status'=>OrderConstant::ORDER_STATUS_PAYED,'order_pay_time'=>time(),'payment_type'=>OrderConstant::PAY_TYPE_ADMIN]);
            $this->orderPayRepository->updateByConditions(['id'=>$re['order_pay_id']] , ['status'=>OrderConstant::ORDER_PUSH_STATUS_SEND]);

            $this->messageService->orders($oid, $re['member_id'], Message::MS_ORDER_PAY);
            DB::commit();
        }catch (Exception $e){
            DB::rollBack();
            return false;
        }

        return true;
    }

    /**
     * Note:确认收货
     * Author:Jurij.cao
     * Date:2022/8/12
     * @param $oid
     * @return bool
     * @return bool
     * @throws BaseException
     */
    public function confirmGoods($oid): bool
    {
        $order = $this->getOne(['oid' => $oid], ['status', 'oid', 'member_id']);
        if ($order['status'] != OrderConstant::ORDER_STATUS_SEND) {
            throw new BaseException(BaseException::BASE_ERROR, '未满足收货状态');
        }
        DB::beginTransaction();
        try {
            $this->updateByConditions(['oid' => $oid, 'status' => OrderConstant::ORDER_STATUS_SEND],
                ['status' => OrderConstant::ORDER_STATUS_ESTIMATE, 'confirm_time' => time()]);
            $this->messageService->orders($oid, $order['member_id'], Message::MS_ORDER_DELIVERY);
            DB::commit();
        } catch (Exception $e) {
            DB::rollBack();
            return false;
        }

        return true;
    }

    // 单品 不做检验
    private function handleCoupon($goods_money, $coupon_receive_id, array $goods = []): array
    {
        // 获取可用优惠券
        $coupon_list = $this->couponReceiveService->memberCoupon(['id'=>$coupon_receive_id,'status'=>0],1,1);
        if(!$coupon_list['total']){
            throw new BaseException(BaseException::BASE_ERROR, '优惠券检测失败，请重试!');
        }

        $v = current($coupon_list['data']);
        $sub_money = $goods_money;
        // 判断指定分类券是否可用

        $_money = 0;// 可参与券的商品金额是多少
        if($v['goods_type'] == 3){ //指定分类可用券
            $ids = explode(',', $v['goods_category']);
            if(!empty($goods)){
                foreach ($goods as $p){
                    if(in_array($p['category_id'], $ids)){
                        $_money += $p['retail_price']*$p['number'];
                    }
                }
                $sub_money = $_money;
            }
        }

        if($v['price'] != 0 && $v['price'] > $sub_money){
            throw new BaseException(BaseException::BASE_ERROR, '优惠券检测失败，请重试!');
        }

        if($v['free_type'] == 1){
            // 满减
            $money = max(bcsub((string)$sub_money, (string)$v['coupon_price'], 2), 0);
            $discount_money = min($v['coupon_price'], $sub_money);
        }else{
            // 满折扣
            $discount = bcmul((string)$sub_money, (string)($v['coupon_price']/10), 2);
            $money = $discount;
            $discount_money = bcsub((string)$sub_money, (string)$discount, 2);
        }

        // 返回数据
        return ['discount_price'=>$discount_money,'money'=>$money,'coupon'=>$v];
    }
}
